(function($){
	var KEY = "jforest.table";
	
	function getValue(record,code){
		
	}
	
	var Cell=function(index,code,value){
		this.index=index,this.code=code;this.value=value;
	}
	Cell.prototype={
		update:function(){
			if(jf.isNotNull(this.newValue)){this.value=this.newValue;this.newValue=null;delete this.newValue;}
		}
	}
	
	/* 文本列 */
	var TextColumn=function(options){
		this.options=$.extend({},options);
		this.arrCells = [];
	}
	TextColumn.prototype={
		createThEl:function(){return $('<th></th>').html(this.options.title)},
		createTdEl:function(table,index,record,$tr){
			var opts=this.options,array = opts.code.split("."),value = record;
			for(var i=0;i<array.length;i++){value = value[array[i]];}
			var cell=new Cell(index,opts.code,value);
			if(this.options.width){
				cell.$td=$('<td style="width:'+this.options.width+'"></td>');
			}else{
				cell.$td=$('<td></td>');
			}
			if($.isFunction(this.options.format)){
				cell.value = this.options.format.apply(table,[record,cell.$td]);
			}
			if(cell.value != undefined){cell.$td.append(cell.value);}
			this.arrCells[index]=cell;return cell.$td;
		},
		updateData:function(table,i,record,$tr){
			var cell = this.arrCells[i],opts=this.options;
			if($.isFunction(this.options.format)){
				var val = this.options.format.apply(table,[record,cell.$td]);
				if(val){cell.$td.html(val);}
			}else if(cell.value != record[opts.code]){
				cell.value = record[opts.code];
				cell.$td.html(cell.value || '');
			}
		}
	}
	/* 按钮列 */
	var IconColumn=function(options){
		this.options=$.extend({width:null},options);
		if(!this.options.width && !$.isFunction(this.options.icons)){this.options.width=20+30*this.options.icons.length;}
		this.arrEl = [];
	}
	IconColumn.prototype={
		createThEl:function(){return $('<th></th>').html(this.options.title).width(this.options.width);},
		createTdEl:function(table,index,record,$tr){
			var $td=$('<td></td>').width(this.options.width),icons=this.options.icons;
			$.each(icons,function(i,item){
				if($.isFunction(item)){item = item.apply(table,[record,$tr]);}
				if(item){
					var btn = new IconButton(item);
					$td.append(btn.createEl(table,record,$tr));
				}
				/*$a = $('<a href="javascript:void(0);" style="margin-right:7px;"></a>');
				if(item.icon){$a.append('<i class="fa '+item.icon+'"></i>');}
				if(item.tooltip){if(item.icon){$a.tooltip({title:item.tooltip});}else{$a.html(item.tooltip)}}
				$a.appendTo($td).click(function(e){item.click.apply(table,[record,$tr,this]);});*/
			});
			this.arrEl.push($td);return $td;
		},
		updateData:function(table,index,record,$tr){
			var $td = this.arrEl[index].html(''),icons=this.options.icons;
			$.each(icons,function(i,item){
				if($.isFunction(item)){item = item.apply(table,[record,$tr]);}
				if(item){
					var btn = new IconButton(item);
					$td.append(btn.createEl(table,record,$tr));
				}
			});
		}
	}
	var IconButton=function(options){
		this.options=$.extend({icon:null,tooltip:null,click:function(){}},options);
		this.icon = this.options.icon;
	}
	IconButton.prototype={
		createEl:function(table,record,$tr){
			var opts=this.options,me=this,isDisplay = true;
			if($.isFunction(opts.display)){
				isDisplay = opts.display.apply(table,[record]);
			}
			if(isDisplay == true){
				this.$el = $('<a href="javascript:void(0);" style="margin-right:7px;"></a>');
				if(opts.icon){this.$el.append('<i class="fa '+opts.icon+'"></i>');}
				if(opts.tooltip){if(opts.icon){this.$el.tooltip({title:opts.tooltip});}else{this.$el.html(opts.tooltip)}}
				this.$el.click(function(e){opts.click.apply(table,[record,me,$tr]);});
			}else{
				this.$el = $('');
			}
			return this.$el;
		},
		changeIcon:function(newIcon){
			this.$el.find('>i').removeClass(this.icon).addClass(newIcon);
			this.icon = newIcon;
		}
	}
	/* 复选框列 */
	var CheckboxColumn=function(options){
		this.options=$.extend({
			width:30,
			displayTitle:true,
			isSingle:false
		},options);
		this.arrCells = [];
	}
	CheckboxColumn.prototype={
		createThEl:function(){
			var opts=this.options,col=this;
			if(opts.displayTitle == true && opts.isSingle == false){
				this.$checkbox = $('<label class="nice-checkbox" style="margin-bottom:0;"><input type="checkbox"></label>');
				this.$checkbox.mousedown(function(event){
					$(this).toggleClass('on');
					if($(this).hasClass('on')){
						$.each(col.arrCells,function(i,cell){
							cell.$td.find('.nice-checkbox').addClass('on');
							cell.$td.find('.nice-checkbox input[type="checkbox"]')[0].checked = true;
						});
					}else{
						$.each(col.arrCells,function(i,cell){
							cell.$td.find('.nice-checkbox').removeClass('on');
							cell.$td.find('.nice-checkbox input[type="checkbox"]')[0].checked = false;
						});
					}
				});
				if(opts.titleClick){
					this.$checkbox.find('input[type="checkbox"]').click(function(){
						opts.titleClick.apply(col,[this.checked]);
					});
				}
				if(opts.values && !$.isArray(opts.values)){
					opts.values = opts.values.split(",");
				}
				return $('<th></th>').append(this.$checkbox).width(this.options.width);
			}else{
				return $('<th></th>').width(this.options.width);
			}
		},
		createTdEl:function(table,index,record,$tr){
			var opts=this.options,cell=new Cell(index,opts.code,record[opts.code]),col=this;

			if(opts.isSingle){
				cell.$td = $('<td><label style="margin-bottom:0;"><input type="radio" name="'+opts.code+'" value="'+cell.value+'"></label></td>');
				if(opts.click){
					cell.$td.find('input[type="radio"]').click(function(){
						opts.click.apply(col,[this.checked,cell.value,record]);
					});
				}
				this.arrCells.push(cell);
			}else{
				cell.$td = $('<td><label class="nice-checkbox" style="margin-bottom:0;"><input type="checkbox" value="'+cell.value+'"></label></td>');
				cell.$td.find('.nice-checkbox').mousedown(function(event){
					$(this).toggleClass('on');
				});
				if(opts.click){
					cell.$td.find('.nice-checkbox input[type="checkbox"]').click(function(){
						opts.click.apply(col,[this.checked,cell.value,record]);
					});
				}
				if(opts.values && $.inArray(cell.value.toString(),opts.values) > -1){
					cell.$td.find('.nice-checkbox').addClass('on');
					cell.$td.find('.nice-checkbox input[type="checkbox"]')[0].checked = true;
				}
				
				this.arrCells.push(cell);
			}
			return cell.$td;
		},
		clear:function(){
			this.arrCells = [];
		},
		getCheckedValues:function(){
			if(this.options.isSingle){
				var values = '';
				$.each(this.arrCells,function(i,cell){
					var $checkbox = cell.$td.find('input[type="radio"]');
					if($checkbox[0].checked == true){
						values = $checkbox.val();
						return false;
					}
				});
				return values;
			}else{
				var values = '';
				$.each(this.arrCells,function(i,cell){
					var $checkbox = cell.$td.find('.nice-checkbox input[type="checkbox"]');
					if($checkbox[0].checked == true){
						values = values+','+$checkbox.val();
					}
				});
				if(values.length>1){values = values.substring(1);}
				return values;
			}
		},
		getCheckedRecord:function(index){
			if(this.options.isSingle){
				var values = '';
				$.each(this.arrCells,function(i,cell){
					var $checkbox = cell.$td.find('input[type="radio"]');
					if($checkbox[0].checked == true){
						values = cell.$td.parent('tr').data('record');
						return false;
					}
				});
				return values;
			}else{
				var values = '',next = 0;
				$.each(this.arrCells,function(i,cell){
					var $checkbox = cell.$td.find('.nice-checkbox input[type="checkbox"]');
					if($checkbox[0].checked == true){
						if(next == index){
							values = cell.$td.parent('tr').data('record');
							return false;
						}
						next = next + 1;
					}
				});
				return values;
			}
		},
		setValues:function(values){
			if($.isArray(values)){
				$.each(this.arrCells,function(i,cell){
					var $checkbox = cell.$td.find('.nice-checkbox input[type="checkbox"]');
					for(var i=0;i<values.length;i++){
						if($checkbox.val() == values[i]){
							$checkbox[0].checked = true;
							break;
						}
					}
				});
			}
		}
	}
	/* 可编辑列 */
	var InputColumn=function(options){
		this.options=$.extend({
			isDisplay:true
		},options);
		this.arrCells = [];
	}
	InputColumn.prototype={
		createThEl:function(){return $('<th></th>').html(this.options.title).width(this.options.width);},
		createTdEl:function(table,index,record,$tr){
			var opts=this.options,cell=new Cell(index,opts.code,record[opts.code]),col=this;
			cell.$td=$('<td style="padding:2px;"></td>').data('_editing',false).width(opts.width);
			if(opts.inputType=='text'){
				cell.$inputEl=$('<input type="text" class="form-control" style="display:none;" value="'+cell.value+'"/>').appendTo(cell.$td);
			}else if(opts.inputType=='checkbox'){
				cell.$inputEl=$('<input type="checkbox" style="display:none;"/>').appendTo(cell.$td);
				cell.$inputEl[0].checked=cell.value;
			}
			cell.$textEl=$('<span style="width:100%;height:100%;">'+cell.value+'</span>').appendTo(cell.$td);
			cell.$td.find('>input').change(function(){
				if(opts.inputType=='checkbox'){
					cell.newValue=cell.$inputEl[0].checked;
				}else{cell.newValue=cell.$inputEl.val();}
				table._editCellData(record,cell);
			});
			/*cell.$td.dblclick(function(){
				if($(this).data('_editing')==true){
					$(this).data('_editing',false);
					if(opts.inputType=='checkbox'){
						cell.newValue=cell.$inputEl[0].checked;
					}else{cell.newValue=cell.$inputEl.val();}
					if(cell.value!==cell.newValue){
						//触发保存事件
						table._editCellData(record,cell);
					}
				}else{$(this).data('_editing',true);}
				cell.$textEl.toggle();cell.$inputEl.toggle().focus();
			});*/
			this.arrCells[index]=cell;
			if($.isFunction(opts.isDisplay)){
				if(opts.isDisplay.apply(this,[record]) == true){
					this.edit(index);
				}
			}else if(opts.isDisplay == true){
				this.edit(index);
			}
			return cell.$td;
		},
		edit:function(index){
			var cell = this.arrCells[index];
			cell.$textEl.hide();cell.$inputEl.show();
		},
		change:function(index,value){
			this.arrCells[index].$td.find('>input').val(value);
		}
	}
	/* 详细描述列 */
	var DetailColumn=function(options){
		this.options=$.extend({
			width:30,
			detailFormat:function(){}
		},options);
		this.arrCells = [];
	}
	DetailColumn.prototype={
		createThEl:function(){return $('<th></th>').html(this.options.title).width(this.options.width);},
		createTdEl:function(table,index,record,$tr){
			var opts=this.options,cell=new Cell(index,opts.code,record[opts.code]),col=this,colsNum=table.options.cols.length;
			cell.$td = $('<td><a href="javascript:void(0);"><i class="fa fa-plus-square"></i></a></td>');
			cell.$td.width(this.options.width);
			cell.$td.find('a').click(function(){
				var $detailTr = cell.$td.data('_detailTr');
			
				$(this).find('i').toggleClass('fa-plus-square');
				$(this).find('i').toggleClass('fa-minus-square');
				
				if(!$detailTr){
					$detailTr = $('<tr><td colspan="'+colsNum+'"></td></tr>');
					$detailTr.find('td').html(opts.detailFormat.apply(opts,[record]));
					cell.$td.data('_detailTr',$detailTr);
				}
				
				if($(this).find('i').hasClass('fa-minus-square')){
					$tr.after($detailTr);
				}else{
					$detailTr.remove();
				}
			});
			this.arrCells[index]=cell;return cell.$td;
		}
	}
	
	var Table = function(element,options){
		this.$el = $(element);
		this.options = $.extend({
			autoLoad:true,
			ajax:{},
			editAjax:null,
			pagingEl:'auto',
			paging:{},
			cols:null //{}或[]
		},options);
		if(this.$el.find('thead').length==0){this.$el.append('<thead></thead>');}
		if(this.$el.find('tbody').length==0){this.$el.append('<tbody></tbody>');}
		if(this.$el.find('tfoot').length==0){this.$el.append('<tfoot></tfoot>');}
		
		this.ajax=jf.getAjax($.extend({param:null},
			this.options.ajax,
			{bindObj:this,
			param:function(opar,par){
				var optsAjax = this.options.ajax;
				var data = null;
				if(this.paging){
					var pagingOpts=this.paging.options;
					data = {pageNo:pagingOpts.pageNo,pageLimit:pagingOpts.pageLimit};
				}
				if($.isFunction(optsAjax.param)){
					if(par || data){
						return optsAjax.param.apply(this,[opar,$.extend(data||{},par||{})]);
					}else{
						return optsAjax.param.apply(this,[opar]);
					}
				}else if(par){
					return $.extend(data||{},optsAjax.param||{},par);
				}else{
					return $.extend(data||{},optsAjax.param||{},opar);
				}
			},
			callback:function(result){
				var opts = this.options;
				if($.isFunction(this.options.ajax.callback)){
					result=this.options.ajax.callback.apply(this,[result])
				};
				if(result){
					$.each(opts.cols,function(i,col){
						if($.isFunction(col.clear)){col.clear()};
					});
					if($.isArray(result)){
						this._buildData(result);
						if(this.paging){
							this.paging.setData({dataTotal:result.length});
						}
					}else{
						this._buildData(result.data || []);
						if(this.paging){
							this.paging.setData({
								dataTotal:result.dataTotal,
								pageTotal:result.pageTotal
							});
						}
					};
				}
			}}
		));
		if(this.options.editAjax){
			this.editAjax=jf.getAjax($.extend({},this.options.editAjax,{
				bindObj:this,
				param:{},
				callback:function(){}
			}));
		}
		this._buildTitle();
		this._analyzeBody();
		
		var table=this;
		if('auto'==this.options.pagingEl){
			this.options.pagingEl=$('<tr><td colspan="'+this.options.cols.length+'"></td></tr>').appendTo(this.$el.find('tfoot')).find('td');
		}
		if(this.options.pagingEl){
			this.paging=$(this.options.pagingEl).jfPaging($.extend(this.options.paging,{
				callback:function(opts){
					if(table.ajax.isValid()){
						var args = $.extend(table.ajax.getParam(),{pageNo:opts.pageNo,pageLimit:opts.pageLimit});
						table.mask();
						table.ajax.load(args);
					}
				}
			}))
		};
		//是否自动加载
		if(this.options.autoLoad == true){this.loadData();}
	}
	
	Table.prototype = {
		_buildTitle:function(){
			var cols=this.options.cols||{},opts=this.options,table=this;
			if($.isArray(cols)){
				var $tr=$('<tr></tr>');
				$.each(cols,function(i,v){
					var col=null;
					if(v.icons){col=new IconColumn(v);}
					else if(v.inputType){col=new InputColumn(v);}
					else if(v.detailFormat){col=new DetailColumn(v);}
					else if(v.checkbox){col=new CheckboxColumn(v);}
					else {col=new TextColumn(v);}
					$tr.append(col.createThEl());
					opts.cols[i] = col;
				});
				this.$el.find('thead').append($tr);
			}else{
				var arrCol=[];
				this.$el.find('thead th').each(function(i,th){
					var code=$(th).attr('data-field'),col=cols[code],title=$(th).html();
					col=$.extend({code:code,title:title},col||{});
					if(col.icons){col=new IconColumn(col);}
					else if(col.inputType){col=new InputColumn(col);}
					else if(col.detailFormat){col=new DetailColumn(col);}
					else if(col.checkbox){
						col=new CheckboxColumn(col);
						$(th).append(col.createThEl().find('label'));
					}
					else {col=new TextColumn(col);}
					arrCol.push(col);
				})
				this.options.cols=arrCol;
			}
		},
		_analyzeBody:function(){
			var self = this;
			this.$el.find('tbody tr').each(function(i,tr){
				var record = {};
				$(tr).find('td').each(function(p,td){
					var col = self.options.cols[p];
					record[col.options.code] = $(td).html();
				})
				$(tr).empty();
				$.each(self.options.cols,function(j,col){
					$(tr).append(col.createTdEl(self,i,record,$(tr)));
				});
				$(tr).data('record',record);
			});
		},
		_buildData:function(data){
			this.unmask(data);
			var self = this;
			$.each(data,function(i,record){
				var $tr = $('<tr></tr>').data('record',record);
				$.each(self.options.cols,function(j,col){
					$tr.append(col.createTdEl(self,i,record,$tr));
				});
				self.$el.find('tbody').append($tr);
			})
		},
		_editCellData:function(record,cell){
			var opts_ea=this.options.editAjax,data,me = this;
			if(this.editAjax.isValid()){
				if($.isFunction(opts_ea.param)){
					data = opts_ea.param.apply(this,[record,cell.code,cell.newValue]);
				}else{
					data = $.extend({},opts_ea.param||{},{
						name:cell.cell,
						value:cell.newValue
					});
				}
				this.editAjax.load(data,function(result){
					opts_ea.callback.apply(me,[result,cell]);
				});
			}
		},
		getCol:function(index){
			return this.options.cols[index];
		},
		mask:function(){
			this.$el.find('tbody').empty();
			this.$el.find('tbody').append('<tr id="tableMaskTr"><td colspan="'+this.options.cols.length+'">'
				+'<div class="alert alert-info" style="text-align:center;"><i class="fa fa-spinner fa-spin"></i> 数据加载中....</div></td></tr>');
		},
		unmask:function(data){
			if(!data || data.length == 0){
				this.$el.find('tbody #tableMaskTr>td').html('<div class="alert alert-warning" style="text-align:center;">没有数据</div>');
			}else if(this.$el.find('tbody #tableMaskTr').length > 0){
				this.$el.find('tbody #tableMaskTr').remove();
			}else{
				this.$el.find('tbody').empty();
			}
		},
		addRecord:function(record,onlyId){
			var opts = this.options,me=this,flag=true;
			if(onlyId){
				this.$el.find('tbody tr').each(function(i,tr){
					var data = $(tr).data('record');
					if(data[onlyId] == record[onlyId]){
						flag = false;
						return false;
					}
				});
			}
			if(flag == true){
				var $tr = $('<tr></tr>').data('record',record);
				$.each(opts.cols,function(j,col){
					$tr.append(col.createTdEl(me,j,record,$tr));
				});
				this.$el.find('tbody').append($tr);
			}
		},
		removeRecord:function(id,value){
			this.$el.find('tbody tr').each(function(i,tr){
				var record = $(tr).data('record');
				if(record[id] == value){
					$(tr).remove();
				}
			});
		},
		loadData:function(args){
			if(this.ajax.isValid()){
				this.mask();
				if(args && args.pageNo && this.paging){
					this.paging.setData({pageNo:args.pageNo});
				}
				this.ajax.load(args);
			}
		},
		loadDataCell:function(key,args){
			var opts = this.options,me = this;
			if(this.ajax.isValid()){
				if(args && args.pageNo && this.paging){
					this.paging.setData({pageNo:args.pageNo});
				}
				this.ajax.load(args,function(result){
					var data = result,arrTr = this.$el.find('tbody tr');
					if(!$.isArray(result)){data = result.data;}
					if(data && data.length > 0){
						me.$el.find('tbody #tableMaskTr').remove();
						$.each(data,function(i,record){
							var isNew = true;
							$.each(arrTr,function(j,tr){
								var oldRecord = $(tr).data('record');
								if(oldRecord && oldRecord[key] == record[key]){
									isNew = false;
									$.each(opts.cols,function(p,col){
										col.updateData(me,j,record,$(tr));
									});
									return false;
								}
							});
							if(isNew == true){
								var $tr = $('<tr></tr>').data('record',record);
								var length = me.$el.find('tbody tr').length;
								$.each(opts.cols,function(p,col){
									$tr.append(col.createTdEl(me,length,record,$tr));
								});
								me.$el.find('tbody').append($tr);
							}
						});
					}else{
						this.mask();
					}
				});
			}
		},
		getValues:function(key){
			var values = '';
			this.$el.find('tbody tr').each(function(i,tr){
				var record = $(tr).data('record');
				if(record[key]){
					values = values+','+record[key];
				}
			});
			if(values.length>1){values = values.substring(1);}
			return values;
		},
		eachRecords:function(callback){
			var records = [],me = this;
			this.$el.find('tbody tr').each(function(i,tr){
				var record = $(tr).data('record');
				if($.isFunction(callback)){
					callback.apply(me,[record]);
				}
				if(record){
					records.push(record);
				}
			});
			return records;
		}
	}
	
	$.fn.jfTable = function(){
		var args = Array.prototype.slice.call(arguments, 0);
		var value = undefined;
		this.each(function () {
			var $this = $(this);
			//throw 'only support table element'
			if (args.length === 0 || typeof(args[0]) === "object") {
				opts = args.length === 0 ? {} : $.extend({}, args[0]);
				$this.data(KEY,new Table(this,opts)); //创建控件
			}else if (typeof(args[0]) === "string"){
				var entity = $this.data(KEY);
                if(entity === undefined){return;}
                value = entity[args[0]].apply(entity, args.slice(1));
			}else{
				 throw 'Invalid arguments to '+KEY+' plugin: ' + args;
			}
	    });
	    return (value === undefined) ? this : value;
	};
	
	$.fn.jfTable.Constructor = Table;
})(window.jQuery)